﻿using Microsoft.Extensions.Configuration;
using Sgr.Domain.Entities;
using Sgr.Exceptions;
using Sgr.UPMS.Domain.LogLogins;
using Sgr.UPMS.Domain.Organizations;
using Sgr.UPMS.Domain.Users;
using Sgr.UPMS.Domain.UserTokens;

namespace Sgr.UPMS.Application.Services
{
    public class UpmsSummaryService : IUpmsSummaryService
    {
        private readonly IUpmsQueryContext _context;
        private readonly IConfiguration _configuration;

        public UpmsSummaryService(IUpmsQueryContext context, IConfiguration configuration)
        {
            _context = context ?? throw new ArgumentNullException(nameof(context));
            _configuration = configuration ?? throw new ArgumentNullException(nameof(configuration));
        }

        /// <summary>
        /// 获取系统总用户数
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>系统总用户数</returns>
        public async Task<int> GetTotalUserCountAsync(CancellationToken cancellationToken = default)
        {
            var query = _context.Query<User>()
                .Where(u => !u.IsDeleted && u.State == EntityStates.Normal);

            return await _context.CountAsync(query, cancellationToken);
        }

        /// <summary>
        /// 获取系统总企业数
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>系统总企业数</returns>
        public async Task<int> GetTotalEnterpriseCountAsync(CancellationToken cancellationToken = default)
        {
            var query = _context.Query<Organization>()
                .Where(o => !o.IsDeleted && o.State == EntityStates.Normal);

            return await _context.CountAsync(query, cancellationToken);
        }

        /// <summary>
        /// 获取指定时间范围内的日活用户数
        /// </summary>
        /// <param name="start">开始时间</param>
        /// <param name="end">结束时间</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>活跃用户数量</returns>
        public async Task<int> GetActivityUserCount(DateTime start, DateTime end, CancellationToken cancellationToken = default)
        {
            if (start >= end)
                throw new BusinessException("开始时间必须小于结束时间。");

            // 查询指定时间范围内成功登录的唯一用户数
            var query = _context.Query<LogLogin>()
                .Where(log => log.LoginTime >= start && log.LoginTime < end)
                //.Where(log => log.Status == true) // 只统计成功登录的记录
                .Select(log => log.LoginName)
                .Distinct();

            return await _context.CountAsync(query, cancellationToken);
        }

        /// <summary>
        /// 获取当前在线用户数（基于有效的刷新令牌）
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>当前在线用户数</returns>
        public async Task<int> GetCurrentOnlineUserCountAsync(CancellationToken cancellationToken = default)
        {
            // 程序中每次颁发访问令牌的时候都会更新并创建刷新令牌，令牌的创建时间其实就访问令牌的颁发时间，
            // 这样我根据令牌的创建时间来判断活跃的用户情况

            // 计算访问令牌有效期的起始时间点
            var accessTokenValidFrom = DateTime.UtcNow.AddSeconds(-1 * GetAccessTokenExpireSeconds());
            var query = _context.Query<UserRefreshToken>()
                .Where(f => f.CreateTime >= accessTokenValidFrom)
                .Select(f => f.UserId)
                .Distinct();

            return await _context.CountAsync(query, cancellationToken);
        }

        /// <summary>
        /// 获取当前在线会话数（基于有效的刷新令牌）
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>当前在线会话数</returns>
        public async Task<int> GetCurrentOnlineSessionCountAsync(CancellationToken cancellationToken = default)
        {
            // 程序中每次颁发访问令牌的时候都会更新并创建刷新令牌，令牌的创建时间其实就访问令牌的颁发时间，
            // 这样我根据令牌的创建时间来判断活跃的用户情况

            // 计算访问令牌有效期的起始时间点
            var accessTokenValidFrom = DateTime.UtcNow.AddSeconds(-1 * GetAccessTokenExpireSeconds());
            var query = _context.Query<UserRefreshToken>()
                .Where(f => f.CreateTime >= accessTokenValidFrom);

            return await _context.CountAsync(query, cancellationToken);
        }

        /// <summary>
        /// 获取访问令牌过期时间（秒）
        /// </summary>
        /// <returns>访问令牌过期时间，默认1800秒（30分钟）</returns>
        private int GetAccessTokenExpireSeconds()
        {
            return _configuration.GetValue<int>("Sgr:Identity:JWT:ExpireSeconds", 1800);
        }
    }
}